﻿using Lib.Security;
using System.IO;
using System.Text;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Serialization;
using JSon = System.Text.Json.JsonSerializer;
using JSonDocuments = System.Text.Json.JsonDocument;

namespace Lib.WPF.Core;
/// <summary>
/// 
/// </summary>
public class Common {
    /// <summary>
    /// 
    /// </summary>
    private static JsonSerializerOptions JavaScriptOptions = new JsonSerializerOptions() {
        // 处理中文转义问题（转义不安全字符） 
        Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
        // 不使用驼峰样式
        PropertyNamingPolicy = null,
        // 忽略循环引用
        ReferenceHandler = ReferenceHandler.IgnoreCycles,
        // 处理注释
        ReadCommentHandling = JsonCommentHandling.Skip,
        // 忽略大小写
        PropertyNameCaseInsensitive = true,
        // 缩进
        WriteIndented = true
    };

    /// <summary>
    /// 判断是否JSON格式文件
    /// </summary>
    public static bool JSonDocument(string Path) {
        if (!File.Exists(Path)) {
            return false;
        }
        try {
            var Content = File.ReadAllText(Path);
            using (JSonDocuments.Parse(Content)) {
                return true;
            }
        } catch {

        }
        return false;
    }
    /// <summary>
    /// 
    /// </summary>
    public static T Deserialize<T>(string Content) {
        try {
            if (!string.IsNullOrEmpty(Content)) {
                return JSon.Deserialize<T>(Content, JavaScriptOptions);
            }
        } catch { 
        
        }
        return default;
    }
    /// <summary>
    /// 
    /// </summary>
    public string Serialize<T>(T That) {
        if (That != null) {
            var Content = JSon.Serialize<T>(That, JavaScriptOptions);
            if (!string.IsNullOrEmpty(Content)) {
                return Content;
            }
        }
        return null;
    }
    /// <summary>
    /// 读取文件
    /// </summary>
    /// <typeparam name="T">返回对象类型</typeparam>
    /// <param name="Path">文件路径</param>
    /// <param name="isBinary">是否二进制文件</param>
    /// <param name="SecretKey">密钥</param>
    /// <returns></returns>
    public static T GetFile<T>(string Path, bool isBinary = false, string SecretKey = null) {
        if (string.IsNullOrEmpty(Path)) {
            return default;
        }
        try {
            var Content = GetFile(Path, isBinary);
            if (!string.IsNullOrEmpty(Content)) {
                if (!string.IsNullOrEmpty(SecretKey)) {
                    Content = Password.Decrypt(Content, SecretKey);
                }
                return JSon.Deserialize<T>(Content, JavaScriptOptions);
            }
        } catch {

        }
        return default;
    }
    /// <summary>
    /// 读取文件
    /// </summary>
    /// <param name="Path">文件路径</param>
    /// <param name="isBinary">是否二进制文件</param>
    /// <returns>返回字符串</returns>
    public static string GetFile(string Path, bool isBinary = false) {
        if (File.Exists(Path)) {
            if (isBinary || Path.EndsWith(".Bin", StringComparison.OrdinalIgnoreCase)) {
                using var Stream = new FileStream(Path, FileMode.Open);
                using var Reader = new BinaryReader(Stream);
                return Encoding.UTF8.GetString(Reader.ReadBytes((int)Stream.Length));
            } else {
                return File.ReadAllText(Path);
            }
        }
        return default;
    }
    /// <summary>
    /// 保存文件
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="That">保存对象</param>
    /// <param name="Path">文件路径</param>
    /// <param name="isBinary">是否保存为二进制文件</param>
    /// <param name="SecretKey"></param>
    /// <returns></returns>
    public static bool SaveFile<T>(T That, string Path, bool isBinary = false, string SecretKey = null) {
        if (That == null || string.IsNullOrEmpty(Path)) {
            return false;
        } else {
            try {
                var Content = JSon.Serialize<T>(That, JavaScriptOptions);
                if (!string.IsNullOrEmpty(Content)) {
                    if (!string.IsNullOrEmpty(SecretKey)) {
                        Content = Password.Encrypt(Content, SecretKey);
                        if (string.IsNullOrEmpty(Content)) {
                            return false;
                        }
                    }
                    if (SaveFile(Content, Path, isBinary)) {
                        return true;
                    }
                }
            } catch {
               
            }
        }
        return false;
    }
    /// <summary>
    /// 保存文件
    /// </summary>
    /// <param name="Path">文件路径</param>
    /// <param name="isBinary">是否保存为二进制文件</param>
    /// <returns>返回字符串</returns>
    public static bool SaveFile(string Content, string Path, bool isBinary = false) {
        try {
            if (isBinary || Path.EndsWith(".Bin", StringComparison.OrdinalIgnoreCase)) {
                if (!string.IsNullOrEmpty(Content)) {
                    using var Stream = new FileStream(Path, FileMode.Create, FileAccess.Write);
                    using var Writer = new BinaryWriter(Stream);
                    Writer.Write(Encoding.UTF8.GetBytes(Content));
                } else {
                    return false;
                }
            } else {
                if (Path.EndsWith(".json", StringComparison.OrdinalIgnoreCase)) {
                    var Code = new Utf8JsonReader(Encoding.UTF8.GetBytes(Content));
                    if (JsonDocument.TryParseValue(ref Code, out var Document)) {
                        Content = JSon.Serialize(Document.RootElement, JavaScriptOptions);
                    }
                }
                if (!string.IsNullOrEmpty(Content)) {
                    File.WriteAllText(Path, Content, Encoding.UTF8);
                } else {
                    return false;
                }
            }
        } catch {
            return false;
        }
        return true;
    }
}
